#ifndef __RISCV_H__
#define __RISCV_H__

#include "types.h"

// 读取 mhartid 寄存器, 获取CPU核心ID
static inline uint64 r_mhartid()
{
  uint64 x;
  asm volatile("csrr %0, mhartid" : "=r" (x) );
  return x;
}

// 读写 satp 寄存器
static inline uint64 r_satp()
{
  uint64 x;
  asm volatile("csrr %0, satp" : "=r" (x) );
  return x;
}

static inline void w_satp(uint64 x)
{
  asm volatile("csrw satp, %0" : : "r" (x));
}

// 刷新TLB
static inline void sfence_vma()
{
  // a sfence.vma instruction, to flush the TLB.
  asm volatile("sfence.vma zero, zero");
}

// Supervisor Address Translation and Protection (SATP) 寄存器
// 保存了页表的物理地址
#define SATP_SV39 (8L << 60)
#define MAKE_SATP(pagetable) (SATP_SV39 | (((uint64)pagetable) >> 12))

// 页表相关定义
#define PGSIZE 4096 // 每个页的大小 (字节)
#define PGSHIFT 12  // 页内偏移的位数

// 将物理地址转换为PTE格式
#define PA2PTE(pa) ((((uint64)pa) >> 12) << 10)

// 将PTE转换为物理地址
#define PTE2PA(pte) (((pte) >> 10) << 12)

// 向上取整到页边界
#define PGROUNDUP(sz)  (((sz)+PGSIZE-1) & ~(PGSIZE-1))
// 向下取整到页边界
#define PGROUNDDOWN(a) (((a)) & ~(PGSIZE-1))

// 页表项 (PTE) 标志位
#define PTE_V (1L << 0) // 有效位 (Valid)
#define PTE_R (1L << 1) // 可读位 (Read)
#define PTE_W (1L << 2) // 可写位 (Write)
#define PTE_X (1L << 3) // 可执行位 (Execute)
#define PTE_U (1L << 4) // 用户位 (User)

// 从虚拟地址中提取三级页表索引
#define PXMASK          0x1FF // 9位掩码
#define PXSHIFT(level)  (PGSHIFT + (9 * (level)))
#define PX(level, va) ((((uint64) (va)) >> PXSHIFT(level)) & PXMASK)

// 页表项和页表类型定义
typedef uint64 pte_t;
typedef uint64 *pagetable_t;


// ========== M/S 模式 CSR/位 定义与读写函数补全 ==========

// mstatus 位
#define MSTATUS_MIE      (1L << 3)
#define MSTATUS_MPP_MASK (3L << 11)
#define MSTATUS_MPP_S    (1L << 11)

// mie 位
#define MIE_MSIE (1L << 3)
#define MIE_MTIE (1L << 7)
#define MIE_MEIE (1L << 11)

// sstatus 位
#define SSTATUS_SIE   (1L << 1)   // S 全局中断使能

// sie 位（使能）
#define SIE_SSIE      (1L << 1)   // S 软件中断使能
#define SIE_STIE      (1L << 5)   // S 定时器中断使能
#define SIE_SEIE      (1L << 9)   // S 外部中断使能

// sip 位（挂起）
#define SIP_SSIP      (1L << 1)   // S 软件中断挂起
#define SIP_STIP      (1L << 5)   // S 定时器中断挂起
#define SIP_SEIP      (1L << 9)   // S 外部中断挂起

// S-mode CSRs
static inline uint64 r_sstatus(void){ uint64 x; asm volatile("csrr %0, sstatus":"=r"(x)); return x; }
static inline void   w_sstatus(uint64 x){ asm volatile("csrw sstatus, %0"::"r"(x)); }

static inline uint64 r_sie(void){ uint64 x; asm volatile("csrr %0, sie":"=r"(x)); return x; }
static inline void   w_sie(uint64 x){ asm volatile("csrw sie, %0"::"r"(x)); }

static inline uint64 r_sip(void){ uint64 x; asm volatile("csrr %0, sip":"=r"(x)); return x; }
static inline void   w_sip(uint64 x){ asm volatile("csrw sip, %0"::"r"(x)); }

static inline void   w_stvec(uint64 x){ asm volatile("csrw stvec, %0"::"r"(x)); }


static inline uint64 r_mstatus(void) { uint64 x; asm volatile("csrr %0, mstatus":"=r"(x)); return x; }
static inline void   w_mstatus(uint64 x) { asm volatile("csrw mstatus, %0"::"r"(x)); }
static inline uint64 r_mie(void) { uint64 x; asm volatile("csrr %0, mie":"=r"(x)); return x; }
static inline void   w_mie(uint64 x) { asm volatile("csrw mie, %0"::"r"(x)); }

static inline void w_mtvec(uint64 x) { asm volatile("csrw mtvec, %0"::"r"(x)); }
static inline void w_mepc(uint64 x)  { asm volatile("csrw mepc, %0"::"r"(x)); }
static inline uint64 r_medeleg(void){ uint64 x; asm volatile("csrr %0, medeleg":"=r"(x)); return x; }
static inline void   w_medeleg(uint64 x){ asm volatile("csrw medeleg, %0"::"r"(x)); }
static inline uint64 r_mideleg(void){ uint64 x; asm volatile("csrr %0, mideleg":"=r"(x)); return x; }
static inline void   w_mideleg(uint64 x){ asm volatile("csrw mideleg, %0"::"r"(x)); }
static inline void   w_mscratch(uint64 x){ asm volatile("csrw mscratch, %0"::"r"(x)); }

// S 态其他 CSR
static inline uint64 r_scause(void){ uint64 x; asm volatile("csrr %0, scause":"=r"(x)); return x; }
static inline uint64 r_sepc(void){ uint64 x; asm volatile("csrr %0, sepc":"=r"(x)); return x; }
static inline void   w_sepc(uint64 x){ asm volatile("csrw sepc, %0"::"r"(x)); }
static inline uint64 r_stval(void){ uint64 x; asm volatile("csrr %0, stval":"=r"(x)); return x; }

// PMP（新增）
static inline void w_pmpcfg0(uint64 x){ asm volatile("csrw pmpcfg0, %0"::"r"(x)); }
static inline void w_pmpaddr0(uint64 x){ asm volatile("csrw pmpaddr0, %0"::"r"(x)); }

static inline uint64 r_tp()
{
  uint64 x;
  asm volatile("mv %0, tp" : "=r"(x));
  return x;
}


#endif // __RISCV_H__